#include <string.h>
#include <stdio.h>
#include "mhscpu.h"

// #define TEST_KEY_CLEAR
// #define TEST_KEY_WRITE_LOCK
// #define TEST_KEY_READ_LOCK
// #define TEST_KEY_CLEAR_ALL
// #define TEST_KEY_REGISTER_LOCK

void NVIC_Configuration(void);
void UART_Configuration(void);
void TIMER_Configuration(void);

void clearBPK(void);
void setBPK(void);
void printBPK(void);

__asm void switch_to_unprivilege(void)
{
    mrs r0,control
    orr r0,#1
    msr control,r0
    bx r14
}

void BPK_ReadLockFun(void)
{
	printf("%s\n", __func__);
    BPK_KeyReadLock(BPK_KEY_Region_0 | BPK_KEY_Region_1 | BPK_KEY_Region_2 | BPK_KEY_Region_3, ENABLE);
}

void BPK_ReadUnlockFun(void)
{
	printf("%s\n", __func__);
    BPK_KeyReadLock(BPK_KEY_Region_0 | BPK_KEY_Region_1 | BPK_KEY_Region_2 | BPK_KEY_Region_3, DISABLE);
}

void BPK_WriteLockFun(void)
{
	printf("%s\n", __func__);
	BPK_KeyWriteLock(BPK_KEY_Region_0 | BPK_KEY_Region_1 | BPK_KEY_Region_2 | BPK_KEY_Region_3, ENABLE);
}

void BPK_WriteUnlockFun(void)
{
	printf("%s\n", __func__);
	BPK_KeyWriteLock(BPK_KEY_Region_0 | BPK_KEY_Region_1 | BPK_KEY_Region_2 | BPK_KEY_Region_3, DISABLE);
}

void BPK_ReadLock_Test(void)
{
	printf("=======================%s=======================\n", __func__);
	printf("write and read lock disable\n");
	BPK_ReadUnlockFun();
	BPK_WriteUnlockFun();
	clearBPK();
    setBPK();
	printf("read lock enable\n");
	BPK_ReadLockFun();
	printBPK();
}

void BPK_WriteLock_Test(void)
{
	printf("=======================%s=======================\n", __func__);
	printf("write and read lock disable\n");
	BPK_ReadUnlockFun();
	BPK_WriteUnlockFun();
	clearBPK();
    setBPK();
	printf("write lock enable\n");
	BPK_WriteLockFun();
	clearBPK();
}

void BPK_KeyClean_Test(void)
{
	printf("=======================%s=======================\n", __func__);
	printf("write and read lock disable\n");
	BPK_ReadUnlockFun();
	BPK_WriteUnlockFun();
    setBPK();
    BPK_KeyClear(BPK_KEY_Region_0);
    printBPK();
    BPK_KeyClear(BPK_KEY_Region_1);
    printBPK();
    BPK_KeyClear(BPK_KEY_Region_2);
    printBPK();
    BPK_KeyClear(BPK_KEY_Region_3);
    printBPK();
}


void BPK_Lock_Test(void)
{
	printf("=======================%s=======================\n", __func__);
	printf("--------Lock WriteLock ReadLock Test-------\n");
	BPK_ReadLockFun();
	BPK_WriteLockFun();
	printf("BPK_LRA = %08X\n", BPK->BPK_LRA);
	printf("BPK_LWA = %08X\n", BPK->BPK_LWA);
	
	printf("\nLock WriteLock ReadLock\n\n");
	BPK_Lock(BPK_LOCK_KeyWriteLock | BPK_LOCK_KeyReadLock, ENABLE);
	BPK_ReadUnlockFun();
	BPK_WriteUnlockFun();
	printf("BPK_LRA = %08X\n", BPK->BPK_LRA);
	printf("BPK_LWA = %08X\n", BPK->BPK_LWA);
	
	printf("\nUnlock WriteLock ReadLock\n\n");
	BPK_Lock(BPK_LOCK_KeyWriteLock | BPK_LOCK_KeyReadLock, DISABLE);
	BPK_ReadUnlockFun();
	BPK_WriteUnlockFun();
	printf("BPK_LRA = %08X\n", BPK->BPK_LRA);
	printf("BPK_LWA = %08X\n", BPK->BPK_LWA);
	
	printf("\n-----------Lock KeyClear Test-------------\n");
	printf("\nUnlock KeyClear\n\n");
	BPK_Lock(BPK_LOCK_KeyClear, ENABLE);
	BPK_KeyClean_Test();
	printf("\nUnlock KeyClear\n\n");
	BPK_Lock(BPK_LOCK_KeyClear, DISABLE);
	BPK_KeyClean_Test();
	
	printf("\n-----------Lock SetScramber Test----------\n");
	setBPK();
	printf("Lock SetScramber Enable\n\n");
	BPK_Lock(BPK_LOCK_SetScramber, ENABLE);
	printf("BPK SetScramber Exe\n");
	BPK_SetScramber(0x12345678);
	printBPK();
	printf("Lock SetScramber Disable\n\n");
	printf("BPK SetScramber Exe\n");
	BPK_Lock(BPK_LOCK_SetScramber, DISABLE);
	BPK_SetScramber(0x12345678);
	printBPK();
	
	printf("\n--------------Lock Reset Test-------------\n");
	setBPK();
    BPK_KeyReadLock(BPK_KEY_Region_0 | BPK_KEY_Region_1, ENABLE);
    BPK_KeyWriteLock(BPK_KEY_Region_0 | BPK_KEY_Region_1, ENABLE);
	printf("BPK_LRA = %08X\n", BPK->BPK_LRA);
	printf("BPK_LWA = %08X\n", BPK->BPK_LWA);
	printf("SEN_EXTS_START = %08X\n", SENSOR->SEN_EXTS_START);
	printf("Lock Reset Enable\n\n");
	BPK_Lock(BPK_LOCK_Reset, ENABLE);
	printf("BPK Reset Exe\n");
	BPK_Reset();
	printBPK();
	printf("BPK_LRA = %08X\n", BPK->BPK_LRA);
	printf("BPK_LWA = %08X\n", BPK->BPK_LWA);
	printf("SEN_EXTS_START = %08X\n", SENSOR->SEN_EXTS_START);
	printf("Lock Reset Disable\n\n");
	BPK_Lock(BPK_LOCK_Reset, DISABLE);
	printf("BPK Reset Exe\n");
	BPK_Reset();
	printBPK();
	printf("BPK_LRA = %08X\n", BPK->BPK_LRA);
	printf("BPK_LWA = %08X\n", BPK->BPK_LWA);
	printf("SEN_EXTS_START = %08X\n\n", SENSOR->SEN_EXTS_START);
	
	SENSOR_EXTCmd(DISABLE);
	SENSOR_EXTPortCmd(SENSOR_Port_All, DISABLE);
	SENSOR_ANACmd(SENSOR_ANA_MESH, DISABLE);
	SENSOR_ClearITPendingBit();
}

void BPK_LockLock_Test(void)
{
	printf("=======================%s=======================\n", __func__);
	printf("lock disable\n");
	BPK_Lock(BPK_LOCK_KeyWriteLock | BPK_LOCK_KeyReadLock |
			 BPK_LOCK_Reset | BPK_LOCK_KeyClear |
			 BPK_LOCK_SetScramber , DISABLE);
	printf("BPK->BPK_LR = %08X\n", BPK->BPK_LR);
	
	printf("lock enable\n");
	BPK_Lock(BPK_LOCK_KeyWriteLock | BPK_LOCK_KeyReadLock |
			 BPK_LOCK_Reset | BPK_LOCK_KeyClear |
			 BPK_LOCK_SetScramber , ENABLE);
	printf("\nBPK_LockLock Exe\n\n");
	BPK_LockLock();
	printf("BPK->BPK_LR = %08X\n", BPK->BPK_LR);

	printf("lock disable\n");
	BPK_Lock(BPK_LOCK_KeyWriteLock | BPK_LOCK_KeyReadLock |
			 BPK_LOCK_Reset | BPK_LOCK_KeyClear |
			 BPK_LOCK_SetScramber , DISABLE);
	printf("BPK->BPK_LR = %08X\n", BPK->BPK_LR);
}

int main(void)
{
	SYSCTRL_APBPeriphClockCmd(SYSCTRL_APBPeriph_UART0 | SYSCTRL_APBPeriph_BPU | SYSCTRL_APBPeriph_GPIO,ENABLE);
	SYSCTRL_APBPeriphResetCmd(SYSCTRL_APBPeriph_UART0 | SYSCTRL_APBPeriph_BPU,ENABLE);
	
	SENSOR_EXTCmd(DISABLE);
	SENSOR_EXTPortCmd(SENSOR_Port_All, DISABLE);
	SENSOR_ANACmd(SENSOR_ANA_MESH, DISABLE);
	SENSOR_ClearITPendingBit();
	
	UART_Configuration();
	NVIC_Configuration();
	
	printf("MegaHunt SCPU BPK Demo V1.0.\r\n");
	
	BPK_ReadLock_Test();
	BPK_WriteLock_Test();
	BPK_KeyClean_Test();
	BPK_Lock_Test();
	BPK_LockLock_Test();

	while(1)
	{
	}

}

void NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	
	NVIC_SetPriorityGrouping(NVIC_PriorityGroup_3);
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM0_0_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 7;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
// 	NVIC_Init(&NVIC_InitStructure);
}

void UART_Configuration(void)
{
	UART_InitTypeDef UART_InitStructure;
	
	GPIO_PinRemapConfig(GPIOA, GPIO_Pin_0 | GPIO_Pin_1, GPIO_Remap_0);
	
	UART_InitStructure.UART_BaudRate = 115200;
	UART_InitStructure.UART_WordLength = UART_WordLength_8b;
	UART_InitStructure.UART_StopBits = UART_StopBits_1;
	UART_InitStructure.UART_Parity = UART_Parity_No;
	
	UART_Init(UART0, &UART_InitStructure);
}

void printBPK(void)
{
	uint32_t key[32];
	uint32_t index = 0;
	
	while(BPK_IsReady() == RESET);

	printf("%s\n", __func__);
	memset(key, 0, sizeof(key));
	BPK_ReadKey(key,sizeof(key)/sizeof(key[0]),0);
	for(index = 0;index < sizeof(key)/sizeof(key[0]);index++)
	{
		printf("%08X ", key[index]);
		if (3 == index % 4)
		{
			printf("\n");
		}
	}
	printf("\n");
	memset(key, 0, sizeof(key));
}

void clearBPK(void)
{
	uint32_t buf[32];
	
	printf("%s\n", __func__);
	while(BPK_IsReady() == RESET);
	
	//clear buf
	memset(buf, 0, sizeof(buf));
	BPK_WriteKey(buf,sizeof(buf)/sizeof(buf[0]),0);
	printBPK();
}

void setBPK(void)
{
	uint32_t buf[32];
	uint32_t index = 0;
	printf("%s\n", __func__);
	while(BPK_IsReady() == RESET);
	
	//set buf 0~X
	for(index = 0;index < sizeof(buf)/sizeof(buf[0]);index++)
	{
		buf[index] = index;
	}
	BPK_WriteKey(buf,sizeof(buf)/sizeof(buf[0]),0);
	printBPK();
}


#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{ 
	/* User can add his own implementation to report the file name and line number,
	 ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

	/* Infinite loop */
	while (1)
	{
	}
}
#endif






